/*
*********************************************************************************************************
*
*	模块名称 : MODSBUS通信程序 （主机）
*	文件名称 : modbus_host.c
*	版    本 : V1.4
*	说    明 : 无线通信程序。通信协议基于MODBUS
*
*********************************************************************************************************
*/
#include "board.h"
#include "crc16.h"
//#include "main.h"
#include "bsp_user_lib.h"
#include "modbus_host.h"

#define TIMEOUT		500		/* 接收命令超时时间, 单位1ms */
#define NUM			1		/* 循环发送次数 */

#define SlaveAddr		mainPar.deviceAdd			/* 面板作为时，主板作从机 */
extern __attribute__((aligned(4))) _Main_t mainPar;
/* 保存每个从机的计数器值 */

extern int16_t printHeadHeatTemp;   // 打印头加热温度
extern int16_t printHeadCurTemp;    // 打印头当前温度
extern uint16_t hFanState;          // 喉管风扇状态（0:关闭，1:打开）
extern uint16_t pFanSpeed;          // 打印风扇速度（0-100）
extern uint16_t LogoState;          // Logo风扇状态（0:关闭，1:打开）

__attribute__((aligned(4))) MODH_T g_tModH;
__attribute__((aligned(4))) uint8_t g_modh_timeout = 0;

void MODH_Poll(void);

//static void MODH_RxTimeOut(void);
static void MODH_AnalyzeApp(void);

static void MODH_Read_01H(void);
static void MODH_Read_02H(void);
static void MODH_Read_03H(void);
static void MODH_Read_04H(void);
//static void MODH_Read_05H(void);
static void MODH_Read_06H(void);
static void MODH_Read_10H(void);

//__attribute__((aligned(4))) VAR_T g_tVar;

/*
*********************************************************************************************************
*	功能说明: 轮训，实现从机数据回复的检查
*	返 回 值: 无
*********************************************************************************************************
*/
void bsp_Idle(void)
{
	MODH_Poll();
	rt_thread_delay( 1 ); 
}
/*
*********************************************************************************************************
*	功能说明: 检查当前时间与上次的差异
*	返 回 值: 返回时间差异
*********************************************************************************************************
*/
uint32_t bsp_CheckRunTime(uint32_t oTime)
{
	return (rt_tick_get() - oTime);
}

/*
*********************************************************************************************************
*	功能说明: 返回当前的时间，单位为ms
*	返 回 值: 时刻
*********************************************************************************************************
*/
uint32_t bsp_GetRunTime(void)
{
	return rt_tick_get();
}
/*
*********************************************************************************************************
*	函 数 名: MODH_SendPacket
*	功能说明: 发送数据包 COM1口
*	形    参: _buf : 数据缓冲区
*			  _len : 数据长度
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_SendPacket(uint8_t *_buf, uint16_t _len)
{
	USART3_DataSend(_buf,_len);
}

/*
*********************************************************************************************************
*	函 数 名: MODH_SendAckWithCRC
*	功能说明: 发送应答,自动加CRC.  
*	形    参: 无。发送数据在 g_tModH.TxBuf[], [g_tModH.TxCount
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODH_SendAckWithCRC(void)
{
	uint16_t crc;
	uint8_t cH,cL;
	
	
	crc = CRC16_Modbus(g_tModH.TxBuf, g_tModH.TxCount);
	cH = (uint8_t)(crc>>8);
	cL = (uint8_t)crc ;
	g_tModH.TxBuf[g_tModH.TxCount++] = cH;
	g_tModH.TxBuf[g_tModH.TxCount++] = cL;	

	MODH_SendPacket(g_tModH.TxBuf, g_tModH.TxCount);
	
//	rt_kprintf("485 Send:");
//	printf_x(&g_tModH.TxBuf[0], g_tModH.TxCount,16);
#if 0	/* 此部分为了串口打印结果,实际运用中可不要 */	
	g_tPrint.Txlen = g_tModH.TxCount;
	memcpy(g_tPrint.TxBuf, g_tModH.TxBuf, g_tModH.TxCount);
#endif
}

/*
*********************************************************************************************************
*	函 数 名: MODH_AnalyzeApp
*	功能说明: 分析应用层协议。处理应答。
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODH_AnalyzeApp(void)
{	
	switch (g_tModH.RxBuf[1])			/* 第2个字节 功能码 */
	{
		case 0x01:	/* 读取线圈状态 */
			MODH_Read_01H();
			break;

		case 0x02:	/* 读取输入状态 */
			MODH_Read_02H();
			break;

		case 0x03:	/* 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值 */
			MODH_Read_03H();
			break;

		case 0x04:	/* 读取输入寄存器 */
			MODH_Read_04H();
			break;

//		case 0x05:	/* 强制单线圈 */
//			MODH_Read_05H();
//			break;

		case 0x06:	/* 写单个寄存器 */
			MODH_Read_06H();
			break;		

		case 0x10:	/* 写多个寄存器 */
			MODH_Read_10H();
			break;
		
		default:
			break;
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send01H
*	功能说明: 发送01H指令，查询1个或多个保持寄存器
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _num : 寄存器个数
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send01H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
	g_tModH.TxCount = 0;
	g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
	g_tModH.TxBuf[g_tModH.TxCount++] = 0x01;		/* 功能码 */	
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */
	
	MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
	g_tModH.fAck01H = 0;		/* 清接收标志 */
	g_tModH.RegNum = _num;		/* 寄存器个数 */
	g_tModH.Reg01H = _reg;		/* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */	
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send02H
*	功能说明: 发送02H指令，读离散输入寄存器
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _num : 寄存器个数
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send02H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
	g_tModH.TxCount = 0;
	g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
	g_tModH.TxBuf[g_tModH.TxCount++] = 0x02;		/* 功能码 */	
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */
	
	MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
	g_tModH.fAck02H = 0;		/* 清接收标志 */
	g_tModH.RegNum = _num;		/* 寄存器个数 */
	g_tModH.Reg02H = _reg;		/* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */	
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send03H
*	功能说明: 发送03H指令，查询1个或多个保持寄存器
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _num : 寄存器个数
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send03H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
	g_tModH.TxCount = 0;
	g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
	g_tModH.TxBuf[g_tModH.TxCount++] = 0x03;		/* 功能码 */	
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */
	
	MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
	g_tModH.fAck03H = 0;		/* 清接收标志 */
	g_tModH.RegNum = _num;		/* 寄存器个数 */
	g_tModH.Reg03H = _reg;		/* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */	
//	memset(g_tModH.TxBuf,0x00,g_tModH.TxCount);
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send04H
*	功能说明: 发送04H指令，读输入寄存器
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _num : 寄存器个数
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send04H(uint8_t _addr, uint16_t _reg, uint16_t _num)
{
	g_tModH.TxCount = 0;
	g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
	g_tModH.TxBuf[g_tModH.TxCount++] = 0x04;		/* 功能码 */	
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */
	
	MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
	g_tModH.fAck04H = 0;		/* 清接收标志 */
	g_tModH.RegNum = _num;		/* 寄存器个数 */
	g_tModH.Reg04H = _reg;		/* 保存03H指令中的寄存器地址，方便对应答数据进行分类 */	
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send05H
*	功能说明: 发送05H指令，写强置单线圈
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _value : 寄存器值,2字节
*	返 回 值: 无
*********************************************************************************************************
*/
//void MODH_Send05H(uint8_t _addr, uint16_t _reg, uint16_t _value)
//{
//	g_tModH.TxCount = 0;
//	g_tModH.TxBuf[g_tModH.TxCount++] = _addr;			/* 从站地址 */
//	g_tModH.TxBuf[g_tModH.TxCount++] = 0x05;			/* 功能码 */	
//	g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;		/* 寄存器编号 高字节 */
//	g_tModH.TxBuf[g_tModH.TxCount++] = _reg;			/* 寄存器编号 低字节 */
//	g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8;		/* 寄存器值 高字节 */
//	g_tModH.TxBuf[g_tModH.TxCount++] = _value;			/* 寄存器值 低字节 */
//	
//	MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */

//	g_tModH.fAck05H = 0;		/* 如果收到从机的应答，则这个标志会设为1 */
//}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send06H
*	功能说明: 发送06H指令，写1个保持寄存器
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _value : 寄存器值,2字节
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send06H(uint8_t _addr, uint16_t _reg, uint16_t _value)
{
	g_tModH.TxCount = 0;
	g_tModH.TxBuf[g_tModH.TxCount++] = _addr;			/* 从站地址 */
	g_tModH.TxBuf[g_tModH.TxCount++] = 0x06;			/* 功能码 */	
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;		/* 寄存器编号 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg;			/* 寄存器编号 低字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _value >> 8;		/* 寄存器值 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _value;			/* 寄存器值 低字节 */
	
	MODH_SendAckWithCRC();		/* 发送数据，自动加CRC */
	
	g_tModH.fAck06H = 0;		/* 如果收到从机的应答，则这个标志会设为1 */
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Send10H
*	功能说明: 发送10H指令，连续写多个保持寄存器. 最多一次支持23个寄存器。
*	形    参: _addr : 从站地址
*			  _reg : 寄存器编号
*			  _num : 寄存器个数n (每个寄存器2个字节) 值域
*			  _buf : n个寄存器的数据。长度 = 2 * n
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Send10H(uint8_t _addr, uint16_t _reg, uint8_t _num, uint8_t *_buf)
{
	uint16_t i;
	
	g_tModH.TxCount = 0;
	g_tModH.TxBuf[g_tModH.TxCount++] = _addr;		/* 从站地址 */
	g_tModH.TxBuf[g_tModH.TxCount++] = 0x10;		/* 从站地址 */	
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg >> 8;	/* 寄存器编号 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _reg;		/* 寄存器编号 低字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num >> 8;	/* 寄存器个数 高字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = _num;		/* 寄存器个数 低字节 */
	g_tModH.TxBuf[g_tModH.TxCount++] = 2 * _num;	/* 数据字节数 */
	
	for (i = 0; i < 2 * _num; i++)
	{
		if (g_tModH.TxCount > H_RX_BUF_SIZE - 3)
		{
			return;		/* 数据超过缓冲区超度，直接丢弃不发送 */
		}
		g_tModH.TxBuf[g_tModH.TxCount++] = _buf[i];		/* 后面的数据长度 */
	}
	
	MODH_SendAckWithCRC();	/* 发送数据，自动加CRC */
	g_tModH.fAck10H = 0;
}

/*
*********************************************************************************************************
*	函 数 名: MODH_ReciveNew
*	功能说明: 串口接收中断服务程序会调用本函数。当收到一个字节时，执行一次本函数。
*	形    参: 
*	返 回 值: 1 表示有数据
*********************************************************************************************************
*/
void MODH_ReciveNew(uint8_t _data)
{
	/*
		3.5个字符的时间间隔，只是用在RTU模式下面，因为RTU模式没有开始符和结束符，
		两个数据包之间只能靠时间间隔来区分，Modbus定义在不同的波特率下，间隔时间是不一样的，
		所以就是3.5个字符的时间，波特率高，这个时间间隔就小，波特率低，这个时间间隔相应就大

		4800  = 7.297ms
		9600  = 3.646ms
		19200  = 1.771ms
		38400  = 0.885ms
	*/
	//uint32_t timeout;

	g_modh_timeout = 10;
	
	//timeout = 35000000 / HBAUD485;		/* 计算超时时间，单位us 35000000*/
	
	/* 硬件定时中断，定时精度us 硬件定时器2用于MODBUS从机, 定时器3用于MODBUS从机主机*/
	//bsp_StartHardTimer(3, timeout, (void *)MODH_RxTimeOut);

	if (g_tModH.RxCount < H_RX_BUF_SIZE)
	{
		g_tModH.RxBuf[g_tModH.RxCount++] = _data;
	}
	
}

/*
*********************************************************************************************************
*	函 数 名: MODH_RxTimeOut
*	功能说明: 超过3.5个字符时间后执行本函数。 设置全局变量 g_rtu_timeout = 1; 通知主程序开始解码。
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
//static void MODH_RxTimeOut(void)
//{
//	g_modh_timeout = 1;
//}

/*
*********************************************************************************************************
*	函 数 名: MODH_Poll
*	功能说明: 接收控制器指令. 1ms 响应时间。
*	形    参: 无
*	返 回 值: 0 表示无数据 1表示收到正确命令
*********************************************************************************************************
*/
void MODH_Poll(void)
{	
	uint16_t crc1;
	
	if (g_modh_timeout != 0)	/* 超过3.5个字符时间后执行MODH_RxTimeOut()函数。全局变量 g_rtu_timeout = 1 */
	{
//		LED1_ON;
		g_modh_timeout --;
		/* 没有超时，继续接收。不要清零 g_tModH.RxCount */
		return ;
	}
//	else 
//	{
//		LED1_ON;
//		g_modh_timeout --;
//	}

	/* 收到命令
		05 06 00 88 04 57 3B70 (8 字节)
			05    :  数码管屏的号站，
			06    :  指令
			00 88 :  数码管屏的显示寄存器
			04 57 :  数据,,,转换成 10 进制是 1111.高位在前,
			3B70  :  二个字节 CRC 码	从05到 57的校验
	*/
	g_modh_timeout = 0;

	if (g_tModH.RxCount < 4)
	{
//		rt_kprintf("err.g_tModH.RxCount < 4\r\n");
		goto err_ret;
	}
	
//	rt_kprintf("Rx:");
//	printf_x(g_tModH.RxBuf,g_tModH.RxCount,g_tModH.RxCount);
	/*判断是否为当前读取的设备数据*/
	if(g_tModH.RxBuf[0] != mainPar.deviceAdd)
	{	
		rt_kprintf(" modbus rec slave add err!add:%d \r\n",g_tModH.RxBuf[0]);
		goto err_ret;	
	}
//	 LED1_OFF;
	/* 计算CRC校验和 */
	crc1 = CRC16_Modbus(g_tModH.RxBuf, g_tModH.RxCount);
	if (crc1 != 0)
	{
		rt_kprintf(" modbus rec crc err!\r\n");
		goto err_ret;
	}
	
	/* 分析应用层协议 */
	MODH_AnalyzeApp();
	
err_ret:
#if 0	/* 此部分为了串口打印结果,实际运用中可不要 */
	g_tPrint.Rxlen = g_tModH.RxCount;
	memcpy(g_tPrint.RxBuf, g_tModH.RxBuf, g_tModH.RxCount);
#endif
	
	g_tModH.RxCount = 0;	/* 必须清零计数器，方便下次帧同步 */
}


/*
*********************************************************************************************************
*	函 数 名: MODH_Read_01H
*	功能说明: 分析01H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODH_Read_01H(void)
{
	uint8_t bytes;
	uint8_t *p;
	
	if (g_tModH.RxCount > 0)
	{
		bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */				
		switch (g_tModH.Reg01H)
		{
			case REG_D01:
				if (bytes == 8)
				{
					p = &g_tModH.RxBuf[3];	
					
					g_tVar.D01 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
					g_tVar.D02 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
					g_tVar.D03 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
					g_tVar.D04 = BEBufToUint16(p); p += 2;	/* 寄存器 */
					
					g_tModH.fAck01H = 1;
				}
				break;
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Read_02H
*	功能说明: 分析02H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODH_Read_02H(void)
{
	uint8_t bytes;
	uint8_t *p;
	
	if (g_tModH.RxCount > 0)
	{
		bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */				
		switch (g_tModH.Reg02H)
		{
			case REG_T01:
				if (bytes == 6)
				{
					p = &g_tModH.RxBuf[3];	
					
//					g_tVar.T01 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
//					g_tVar.T02 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
//					g_tVar.T03 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
					
					g_tModH.fAck02H = 1;
				}
				break;
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Read_04H
*	功能说明: 分析04H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODH_Read_04H(void)
{
	uint8_t bytes;
	uint8_t *p;
	
	if (g_tModH.RxCount > 0)
	{
		bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */				
		switch (g_tModH.Reg04H)
		{
			case REG_T01:
				if (bytes == 2)
				{
					p = &g_tModH.RxBuf[3];	
					
					g_tVar.A01 = BEBufToUint16(p); p += 2;	/* 寄存器 */	
					
					g_tModH.fAck04H = 1;
				}
				break;
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODH_Read_05H
*	功能说明: 分析05H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
//static void MODH_Read_05H(void)
//{
//	if (g_tModH.RxCount > 0)
//	{
//		if (g_tModH.RxBuf[0] == SlaveAddr)		
//		{
//			g_tModH.fAck05H = 1;		/* 接收到应答 */
//		}
//	};
//}

/*
*********************************************************************************************************
*	函 数 名: MODH_Read_06H
*	功能说明: 分析06H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
//static void MODH_Read_06H(void)
//{
//	if (g_tModH.RxCount > 0)
//	{
//		if (g_tModH.RxBuf[0] == SlaveAddr)		
//		{
//			g_tModH.fAck06H = 1;		/* 接收到应答 */
//		}
//	}
//}


/*
*********************************************************************************************************
*	函 数 名: MODH_Read_03H
*	功能说明: 分析03H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Read_03H(void)
{
	uint8_t bytes;
	uint8_t *p;
	
	if (g_tModH.RxCount > 0)
	{	
		//打印仓温度计回复
		if(mainPar.deviceAdd == 0x01)
		{
			switch( g_tModH.RxBuf[1] )
			{
				case 0x03://温湿度回传，要求读取的时候要连读回来
//					if((((int16_t)g_tModH.RxBuf[3]<< 8)|(g_tModH.RxBuf[4])) >= -10)
//					{
//						if((((int16_t)g_tModH.RxBuf[3]<< 8)|(g_tModH.RxBuf[4])) <= 100)
//							{
//								printf_x(g_tModH.RxBuf,14,14);
								mainPar.temp = ((uint16_t)g_tModH.RxBuf[3]<< 8)|(g_tModH.RxBuf[4]);
								mainPar.hum =  ((uint16_t)g_tModH.RxBuf[5]<< 8)|(g_tModH.RxBuf[6]);
							//	mainPar.Zhigh = ((uint16_t)g_tModH.RxBuf[9]<< 8)|(g_tModH.RxBuf[10]);
								//使用自己公司设计的电路板，关闭这个设置
//								if(((mainPar.temp - mainPar.Roomtemp) > 20)|((mainPar.Roomtemp - mainPar.temp) > 20))
//								{
//									mainPar.temp = mainPar.Roomtemp;
//									mainPar.hum = mainPar.Roomhum;
//								}
									
								
								g_tModH.fAck03H = 1;
//							
				
					break;
			}
		}
		// 打印头设备回复
        else if (mainPar.deviceAdd == 0x03)
        {
            switch (g_tModH.RxBuf[1])
            {
                case 0x03: // 功能码0x03（读保持寄存器）
                    bytes = g_tModH.RxBuf[2]; // 数据长度（字节数 = 寄存器数量 × 2）
                    p = &g_tModH.RxBuf[3];  // 数据起始指针
                    // 根据寄存器地址（g_tModH.Reg03H）解析数据
                    switch (g_tModH.Reg03H)
                    {
						//喉管风扇状态
						case 0x01:
							//if (bytes >= 2) {
							mainPar.hFanState = ((uint16_t)p[0] << 8) | ((uint16_t)p[1]); 
							//}
							// rt_kprintf("hFanState date:");
							// printf_x(&g_tModH.RxBuf[3],2,2);
							g_tModH.fAck03H = 1;
							break;

						//	打印头LOGO灯状态
						case 0x02:
							//if (bytes >= 2) {
							mainPar.LogoState = ((uint16_t)p[0] << 8) | ((uint16_t)p[1]); 
							//}
							// rt_kprintf("LogoState date:");
							// printf_x(&g_tModH.RxBuf[3],2,2);
							g_tModH.fAck03H = 1;
							break;
						
						case 0x07:
							// 打印头风扇速度
							mainPar.pFanSpeed = ((uint16_t)p[0] << 8) | ((uint16_t)p[1]);
							// rt_kprintf("pFanSpeed date:");
							// printf_x(&g_tModH.RxBuf[9], 2, 2);

							// 打印头加热温度
							p += 2;
							mainPar.printHeadHeatTemp = ((uint16_t)p[0] << 8) | ((uint16_t)p[1]);
							// rt_kprintf("printHeadHeatTemp date:");
							// printf_x(&g_tModH.RxBuf[3], 2, 2);

							// 打印头当前温度
							p += 2;
							mainPar.printHeadCurTemp = ((uint16_t)p[0] << 8) | ((uint16_t)p[1]);
							writeMdodbusReg(Mreg_Print_Temp,mainPar.printHeadCurTemp);
							// rt_kprintf("printHeadCurTemp date:");
							// printf_x(&g_tModH.RxBuf[5], 2, 2);

							g_tModH.fAck03H = 1; // 03H 指令响应成功
							break;	
                    }
            }
        }
		//一号耗材读卡器回复
		else if(mainPar.deviceAdd == 0x06)
		{
			switch( g_tModH.Reg03H )
			{
				case 0x00://UID的回传数据
					writeMdodbusReg(Mreg_Fila1UID1,((uint16_t)g_tModH.RxBuf[3]<< 8)|(g_tModH.RxBuf[4]));
					writeMdodbusReg(Mreg_Fila1UID2,((uint16_t)g_tModH.RxBuf[5]<< 8)|(g_tModH.RxBuf[6]));
					g_tModH.fAck03H = 1;
					break;
				case 0x12://第一扇区密码
					mainPar.Fila1Pass1= ((uint16_t)g_tModH.RxBuf[3]<< 8)|(g_tModH.RxBuf[4]);
					mainPar.Fila1Pass2= ((uint16_t)g_tModH.RxBuf[5]<< 8)|(g_tModH.RxBuf[6]);
					mainPar.Fila1Pass3= ((uint16_t)g_tModH.RxBuf[7]<< 8)|(g_tModH.RxBuf[8]);
					g_tModH.fAck03H = 1;
					break;
				case 0x500://第一扇区8字节数据
					mainPar.Fila1Data1= ((uint16_t)g_tModH.RxBuf[3]<< 8)|(g_tModH.RxBuf[4]);
					mainPar.Fila1Data2= ((uint16_t)g_tModH.RxBuf[5]<< 8)|(g_tModH.RxBuf[6]);
					mainPar.Fila1Data3= ((uint16_t)g_tModH.RxBuf[7]<< 8)|(g_tModH.RxBuf[8]);
					mainPar.Fila1Data4= ((uint16_t)g_tModH.RxBuf[9]<< 8)|(g_tModH.RxBuf[10]);
					rt_kprintf("NFC 1 485 read date:");
					printf_x(&g_tModH.RxBuf[3],8,8);
					g_tModH.fAck03H = 1;
					break;				
			}
		}
		
		else if(mainPar.deviceAdd == 0x0A)
		//获取外部Y块检测板的值
		{
//			printf_x(g_tModH.RxBuf,10,12);
// 			bytes = g_tModH.RxBuf[4];
// //			rt_kprintf("RxBuf[4]:%X-RxBuf[5]:%X-RxBuf[6]:%X\r\n",g_tModH.RxBuf[4],g_tModH.RxBuf[5],g_tModH.RxBuf[6]);
// 			writeMdodbusReg(Mreg_Limit_Fila1,(bytes&0x01));
// 			writeMdodbusReg(Mreg_Limit_FilaA2,((bytes>>0x01)&0x01));
// 			writeMdodbusReg(Mreg_Limit_Fila2,((bytes>>0x02)&0x01));
// 			writeMdodbusReg(Mreg_Limit_FilaB2,((bytes>>0x03)&0x01));
// 			writeMdodbusReg(Mreg_Limit_FilaY,((bytes>>0x04)&0x01));
// 			mainPar.FilaDist = (((uint16_t)g_tModH.RxBuf[5]<< 8)|(g_tModH.RxBuf[6]));
		
// 			writeMdodbusReg(Mreg_Distance,mainPar.FilaDist);
			
//			rt_kprintf("02:Roomtemp:%d Roomhum:%d\r\n",(int16_t)mainPar.Roomtemp,(int16_t)mainPar.Roomhum);	
			// mainPar.Roomtemp = (((uint16_t)g_tModH.RxBuf[7]<< 8)|(g_tModH.RxBuf[8]));
			// writeMdodbusReg(Mreg_ROOM_TEMP,mainPar.Roomtemp);
			// mainPar.Roomhum = (((uint16_t)g_tModH.RxBuf[9]<< 8)|(g_tModH.RxBuf[10]));
			// writeMdodbusReg(Mreg_ROOM_HUM,mainPar.Roomhum);
//			ErrRoomTempCount = 0;

		//	g_tModH.fAck03H = 1;
		}
		//陀螺仪角度回传
		// else {
		// 	bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */		
		// 	switch (g_tModH.Reg03H)
		// 	{
		// 		case 0x3D: //角度回传
		// 			mainPar.fAngleX = (((uint16_t)g_tModH.RxBuf[3]<< 8)|(g_tModH.RxBuf[4]))/ 32768.0f * 180.0f*100;
		// 			mainPar.fAngleY = (((uint16_t)g_tModH.RxBuf[5]<< 8)|(g_tModH.RxBuf[6]))/ 32768.0f * 180.0f*100;
		// 			mainPar.fAngleZ = (((uint16_t)g_tModH.RxBuf[7]<< 8)|(g_tModH.RxBuf[8]))/ 32768.0f * 180.0f*100;
		// 			g_tModH.fAck03H = 1;
		// 			break;	
		// 		default:{
		// 			if((g_tModH.Reg03H >= mUID_PAR) | (g_tModH.Reg03H <= mUID_MAX))
		// 			{
		// 				g_tModH.fAck03H = 1;
		// 			}
		// 			else {
		// 				rt_kprintf("Read_03H,not comm:%d\r\n",g_tModH.Reg03H);
		// 			}
		// 		}
		// 	}
		// }
	}
}
/*
*********************************************************************************************************
*	函 数 名: MODH_Read_06H
*	功能说明: 分析06H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Read_06H(void)
{
	uint8_t bytes;
	uint8_t *p;
	
	if (g_tModH.RxCount > 0)
	{
		bytes = g_tModH.RxBuf[2];	/* 数据长度 字节数 */				
		switch (g_tModH.fAck06H)
		{
			case mDEVICE_MODE:

					p = &g_tModH.RxBuf[3];	
					rt_kprintf("slave mode:%d\r\n",p[3]);
					g_tModH.fAck06H = 1;
				break;	
			default:{
				if((g_tModH.fAck06H >= mUID_PAR) | (g_tModH.fAck06H <= mUID_MAX))
				{
					p = &g_tModH.RxBuf[3];	
					rt_kprintf("mUID_BUFF\r\n");	
					//printf_x(p,bytes,bytes);
//					cardAddSever(p,bytes/18);
					g_tModH.fAck06H = 1;
				}
				else {
					rt_kprintf("fAck06H,not comm:%d\r\n",g_tModH.fAck06H);
				}
			}break;
		}
	}
}
/*
*********************************************************************************************************
*	函 数 名: MODH_Read_10H
*	功能说明: 分析10H指令的应答数据
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void MODH_Read_10H(void)
{
	/*
		10H指令的应答:
			从机地址                11
			功能码                  10
			寄存器起始地址高字节	00
			寄存器起始地址低字节    01
			寄存器数量高字节        00
			寄存器数量低字节        02
			CRC校验高字节           12
			CRC校验低字节           98
	*/
	if (g_tModH.RxCount > 0)
	{
		if (g_tModH.RxBuf[0] == SlaveAddr)		
		{
			g_tModH.fAck10H = 1;		/* 接收到应答 */
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODH_ReadParam_01H
*	功能说明: 单个参数. 通过发送01H指令实现，发送之后，等待从机应答。
*	形    参: 无
*	返 回 值: 1 表示成功。0 表示失败（通信超时或被拒绝）
*********************************************************************************************************
*/
uint8_t MODH_ReadParam_01H(uint16_t _reg, uint16_t _num)
{
	int32_t time1;
	uint8_t i;
	
	for (i = 0; i < NUM; i++)
	{
		MODH_Send01H (SlaveAddr, _reg, _num);		  /* 发送命令 */
		time1 = bsp_GetRunTime();	/* 记录命令发送的时刻 */
		
		while (1)				/* 等待应答,超时或接收到应答则break  */
		{
			bsp_Idle();

			if (bsp_CheckRunTime(time1) > TIMEOUT)		
			{
				break;		/* 通信超时了 */
			}
			
			if (g_tModH.fAck01H > 0)
			{
				break;		/* 接收到应答 */
			}
		}
		
		if (g_tModH.fAck01H > 0)
		{
			break;			/* 循环NUM次，如果接收到命令则break循环 */
		}
	}
	
	if (g_tModH.fAck01H == 0)
	{
		return 0;
	}
	else 
	{
		return 1;	/* 01H 读成功 */
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODH_ReadParam_02H
*	功能说明: 单个参数. 通过发送02H指令实现，发送之后，等待从机应答。
*	形    参: 无
*	返 回 值: 1 表示成功。0 表示失败（通信超时或被拒绝）
*********************************************************************************************************
*/
uint8_t MODH_ReadParam_02H(uint16_t _reg, uint16_t _num)
{
	int32_t time1;
	uint8_t i;
	
	for (i = 0; i < NUM; i++)
	{
		MODH_Send02H (SlaveAddr, _reg, _num);
		time1 = bsp_GetRunTime();	/* 记录命令发送的时刻 */
		
		while (1)
		{
			bsp_Idle();

			if (bsp_CheckRunTime(time1) > TIMEOUT)		
			{
				break;		/* 通信超时了 */
			}
			
			if (g_tModH.fAck02H > 0)
			{
				break;
			}
		}
		
		if (g_tModH.fAck02H > 0)
		{
			break;
		}
	}
	
	if (g_tModH.fAck02H == 0)
	{
		return 0;
	}
	else 
	{
		return 1;	/* 02H 读成功 */
	}
}
/*
*********************************************************************************************************
*	函 数 名: MODH_ReadParam_03H
*	功能说明: 单个参数. 通过发送03H指令实现，发送之后，等待从机应答。
*	形    参: 无
*	返 回 值: 1 表示成功。0 表示失败（通信超时或被拒绝）
*********************************************************************************************************
*/
uint8_t MODH_ReadParam_03H(uint16_t _reg, uint16_t _num)
{
//	uint32_t time1;
	uint8_t i;
	uint32_t timeS = 0;
	
	for (i = 0; i < NUM; i++)
	{
		MODH_Send03H (SlaveAddr, _reg, _num);
//		time1 = bsp_GetRunTime();	/* 记录命令发送的时刻 */
		
		while (1)
		{
			bsp_Idle();
			
//			if (bsp_CheckRunTime(time1) > TIMEOUT)	
			if(timeS++ >= TIMEOUT)
			{
				rt_kprintf("03H slave rec time out.add:%d _reg:0x%x time:%d ms\r\n",SlaveAddr,_reg,TIMEOUT);
				break;		/*通信超时了*/
			}
			//通信完成
			if (g_tModH.fAck03H > 0)
			{
//				rt_kprintf("03H slave: %d _reg:0x%d return data time:%d ms\r\n",SlaveAddr,_reg,timeS);
				break;
			}
		}
		
		if (g_tModH.fAck03H > 0)
		{
			break;
		}
	}
	
	if (g_tModH.fAck03H == 0)
	{
		return 0;	/* 通信超时了 */
	}
	else 
	{
		return 1;	/* 读03H参数成功 */
	}
}


/*
*********************************************************************************************************
*	函 数 名: MODH_ReadParam_04H
*	功能说明: 单个参数. 通过发送04H指令实现，发送之后，等待从机应答。
*	形    参: 无
*	返 回 值: 1 表示成功。0 表示失败（通信超时或被拒绝）
*********************************************************************************************************
*/
uint8_t MODH_ReadParam_04H(uint16_t _reg, uint16_t _num)
{
	int32_t time1;
	uint8_t i;
	
	for (i = 0; i < NUM; i++)
	{
		MODH_Send04H (SlaveAddr, _reg, _num);
		time1 = bsp_GetRunTime();	/* 记录命令发送的时刻 */
		
		while (1)
		{
			bsp_Idle();

			if (bsp_CheckRunTime(time1) > TIMEOUT)		
			{
				break;		/* 通信超时了 */
			}
			
			if (g_tModH.fAck04H > 0)
			{
				break;
			}
		}
		
		if (g_tModH.fAck04H > 0)
		{
			break;
		}
	}
	
	if (g_tModH.fAck04H == 0)
	{
		return 0;	/* 通信超时了 */
	}
	else 
	{
		return 1;	/* 04H 读成功 */
	}
}
/*
*********************************************************************************************************
*	函 数 名: MODH_WriteParam_05H
*	功能说明: 单个参数. 通过发送05H指令实现，发送之后，等待从机应答。
*	形    参: 无
*	返 回 值: 1 表示成功。0 表示失败（通信超时或被拒绝）
*********************************************************************************************************
*/
//uint8_t MODH_WriteParam_05H(uint16_t _reg, uint16_t _value)
//{
//	int32_t time1;
//	uint8_t i;

//	for (i = 0; i < NUM; i++)
//	{
//		MODH_Send05H (SlaveAddr, _reg, _value);
//		time1 = bsp_GetRunTime();	/* 记录命令发送的时刻 */
//		
//		while (1)
//		{
//			bsp_Idle();
//			
//			/* 超时大于 TIMEOUT，则认为异常 */
//			if (bsp_CheckRunTime(time1) > TIMEOUT)		
//			{
//				break;	/* 通信超时了 */
//			}
//			
//			if (g_tModH.fAck05H > 0)
//			{
//				break;
//			}
//		}
//		
//		if (g_tModH.fAck05H > 0)
//		{
//			break;
//		}
//	}
//	
//	if (g_tModH.fAck05H == 0)
//	{
//		return 0;	/* 通信超时了 */
//	}
//	else
//	{
//		return 1;	/* 05H 写成功 */
//	}
//}

/*
*********************************************************************************************************
*	函 数 名: MODH_WriteParam_06H
*	功能说明: 单个参数. 通过发送06H指令实现，发送之后，等待从机应答。循环NUM次写命令
*	形    参: 无
*	返 回 值: 1 表示成功。0 表示失败（通信超时或被拒绝）
*********************************************************************************************************
*/
uint8_t MODH_WriteParam_06H(uint16_t _reg, uint16_t _value)
{
	int32_t time1;
	uint8_t i;
	uint32_t timeS = 0;
	
	for (i = 0; i < NUM; i++)
	{	
		MODH_Send06H (SlaveAddr, _reg, _value);
//		time1 = bsp_GetRunTime();	/* 记录命令发送的时刻 */
				
		while (1)
		{
			bsp_Idle();
		
			if(timeS++ >= TIMEOUT)
			{
				rt_kprintf("slave rec time out.add:%d time:%d ms\r\n",SlaveAddr,TIMEOUT);
//				time1 = 0;
				break;
			}
			
			if (g_tModH.fAck06H > 0)
			{
//				rt_kprintf("slave: %d return data time:%d ms\r\n",SlaveAddr,timeS);
//				time1 = 0;
				break;
			}
		}
		
		if (g_tModH.fAck06H > 0)
		{
			break;
		}
	}
	
	if (g_tModH.fAck06H == 0)
	{
		return 0;	/* 通信超时了 */
	}
	else
	{
		return 1;	/* 写入06H参数成功 */
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODH_WriteParam_10H
*	功能说明: 单个参数. 通过发送10H指令实现，发送之后，等待从机应答。循环NUM次写命令
*	形    参: 无
*	返 回 值: 1 表示成功。0 表示失败（通信超时或被拒绝）
*********************************************************************************************************
*/
uint8_t MODH_WriteParam_10H(uint16_t _reg, uint8_t _num, uint8_t *_buf)
{
//	int32_t time1;
	uint8_t i;
	uint32_t timeS = 0;

	for (i = 0; i < NUM; i++)
	{	
		MODH_Send10H(SlaveAddr, _reg, _num, _buf);
		//time1 = bsp_GetRunTime();	/* 记录命令发送的时刻 */
				
		while (1)
		{
			bsp_Idle();
		
			if(timeS++ >= TIMEOUT)
			//if (bsp_CheckRunTime(time1) > TIMEOUT)		
			{
				rt_kprintf("10H slave wrte time out.SlaveAddr:%d time:%d ms\r\n",SlaveAddr,TIMEOUT);
				break;
			}
			
			if (g_tModH.fAck10H > 0)
			{
//				rt_kprintf("10H slave: %d _reg:0x%d return data time:%d ms\r\n",SlaveAddr,_reg,timeS);
				break;
			}
		}
		
		if (g_tModH.fAck10H > 0)
		{
			break;
		}
	}
	
	if (g_tModH.fAck10H == 0)
	{
		return 0;	/* 通信超时了 */
	}
	else
	{
		return 1;	/* 写入10H参数成功 */
	}
}


